
// 图书管理系统
// 基本功能：至少包含图书的增删改查（添加、删除、修改、全部查询、条件查询）
// 可选功能：借还书管理，以及其他相关功能

/*
基本要求 (合格)
1、必须自主完成，不得抄袭。
2、至少具备基础数据的增、删、改、查。
3、使用面向对象编程技术，除了 main() 函数，不应该有其他全局函数。
4、使用 C++ 的输入输出控制方法，不应该使用 C 语言的输入输出函数。
其他要求 (优秀)
1、所有项目数据应当持久化，保存在文件中。
2、存储字符串时建议用定长的字符数组，不建议用 string 和字符指针。
*/

// 结合文件进行加载，每次运行都加载到文件

/*
逻辑：
先确定基类，有以下几大类：
1、用户 --------------> 用户属性和操作
2、图书 --------------> 书的属性和操作
3、登录 --------------> 功能展示
由基类衍生出子类
1、用户------>图书管理员、普通用户
不同的用户不同的功能
0、所有用户：设置密码，设置用户名------>登录界面
1、图书管理员：增加书，删除书，统计书
2、普通用户：借书，还书
*/

/*
用的技术：虚继承，类与对象，函数模板
*/

#include <iostream>
#include <stdbool.h>
#include <cstring>
#include <string>
#include <fstream>
#include <chrono>

using namespace std;

/***************************************** 声明 ******************************************************/


// 登录页
class Log
{
private:
	int option = 1;
public:
	Log();

	void Register();
	void Login();
};

//Book类
class Book {
public:
	string title;// 书名
	string author;//作者
	string publisher;// 出版社
	double price;// 价格
	bool isborrowed;// bool:真，true，假：false
	//标记是否被借出
	string borrower;// 借书人
	string returndate;// 归还时间
	string location;// 存放的位置
	int code;// 书的编号

public:
	string GetTitle(); //
	string& GetAuthor();
	string GetPublisher();
	double GetPrice();
	bool IsBorrowed();
	string GetBorrower();
	string GetReturnDate();
	string GetLocation();
	int GetCode();

	bool BorrowBook1(string name);
	void ReturnBook1();

	void operator=(const Book& source);
};

// 用户类
class Client
{
public:
	// 用户名字，用户密码
	string name, password;

	void operator=(const Client& source);
};

// 普通用户
class Simple : public Client
{
public:
	void SimpleRegister();// 普通用户的注册
	void SimpleLogin();// 普通用户的登录
	void BorrowBook();// 借书
	void ReturnBook();// 还书
};

// 管理员
class Admin : public Client
{
public:
	void AdminRegister();// 注册
	void AdminLogin();//登录
	void AddBook();// 增加图书
	void DelteBook();// 删除图书
	void CheckBook();// 查看书目
	void CheckClient();// 查看用户
	void DeleteClient();// 删除用户
};

// 大驼峰命名法：每个单词的首字母大写

void Load();
void Down();


Simple S[1000];
Admin A[1000];
Book B[1000];
int simplenum = 0, adminnum = 0, booknum = 0;


/***************************************** 实现 ******************************************************/

template <typename T>
int FindName(string& name, T arr[], int size)
{
	int num = 0;
	while (num < size)
	{
		if (arr[num].name == name)
			return num;
		num++;
	}

	return size;
}
// 代码的复用

// 登录页
Log::Log()
{
	while (option)// 选项
	{
		cout << "----------------------------------------------------------------" << endl;
		cout << "|          请输入你所需要的功能前的序号来选择功能              |" << endl;
		cout << "|          1. 注册                 2. 登录                     |" << endl;
		cout << "|          0. 退出                                             |" << endl;
		cout << "----------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			Register();
		}
		else if (option == 2)
		{
			Login();
		}
		else if (option != 0)
			cout << "选择失败，请重新选择" << endl;
	}
}

void Log::Register()
{
	while (option)
	{
		cout << "---------------------------------------------------------------" << endl;
		cout << "|          请输入你要注册的身份前的序号来选择功能              |" << endl;
		cout << "|          1. 管理员               2. 普通用户                 |" << endl;
		cout << "|          0. 退出                                             |" << endl;
		cout << "---------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			Admin temp;
			temp.AdminRegister();
			temp.AdminLogin();
			break;
		}
		else if (option == 2)
		{
			Simple temp;
			temp.SimpleRegister();
			temp.SimpleLogin();
			break;
		}
		else if (option != 0)
			cout << "选择失败，请重新选择" << endl;
	}
}

void Log::Login()
{
	while (option)
	{
		cout << "---------------------------------------------------------------" << endl;
		cout << "|          请输入你要登录的身份前的序号来选择功能              |" << endl;
		cout << "|          1. 管理员               2. 普通用户                 |" << endl;
		cout << "|          0. 退出                                             |" << endl;
		cout << "---------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			Admin temp;
			temp.AdminLogin();
		}
		else if (option == 2)
		{
			Simple temp;
			temp.SimpleLogin();
			break;
		}
		else if (option != 0)
			cout << "选择失败，请重新选择" << endl;
	}
}

// 用户
void Client::operator=(const Client& source)
{
	this->name = source.name;
	this->password = source.password;
}

// 普通用户
void Simple::SimpleRegister()
{
	while (1)
	{
		cout << "请输入你要注册的用户名:>";
		cin >> name;
		if (FindName(name, S, simplenum) < simplenum)
		{
			cout << "用户名已存在" << endl;
			continue;
		}

		string password1;
		cout << "请输入你要设置的密码: > ";
		cin >> password1;
		cout << "重复你设置的密码:> ";
		cin >> password;
		// if (strcmp(password.c_str(), password1.c_str()) == 0)
		if (password == password1)
		{
			S[simplenum].name = name;
			S[simplenum].password = password;
			simplenum++;
			cout << "普通用户注册成功" << endl;
			break;
		}

		// 到这里两个密码肯定不一样
		cout << "两次密码不一致，请重新输入" << endl;
	}
}

void Simple::SimpleLogin()
{
	int flag = 0;
	while (1)
	{
		cout << "请输入你要登录的普通用户用户名:>";
		cin >> name;
		int position = FindName(name, S, simplenum);
		if (position >= simplenum)
		{
			cout << "用户不存在" << endl;
			flag = 1;
			break;
		}

		cout << "请输入你的密码: > ";
		cin >> password;
		if (password == S[position].password)
		{
			cout << "登录成功" << endl;
			break;
		}

		// 到这里密码肯定不对
		cout << "密码错误，请重新输入" << endl;
	}

	if (flag)
		return;

	int option = 1;
	while (option)
	{
		cout << "---------------------------------------------------------------" << endl;
		cout << "|          请输入你需要的功能                                  |" << endl;
		cout << "|          1. 借书                  2. 还书                    |" << endl;
		cout << "|          3. 查询书                0. 退出                    |" << endl;
		cout << "---------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			BorrowBook();
		}
		else if (option == 2)
		{
			ReturnBook();
		}
		else if (option == 3)
		{
			Admin temp;
			temp.CheckBook();
		}
		else if (option != 0)
		{
			cout << "选择错误，请重新输入" << endl;
		}
	}
}

void Simple::BorrowBook()
{
	cout << "功能：借书" << endl;
	Admin temp1;
	temp1.CheckBook();
	if (booknum != 0)
	{
		Book temp;
		temp.BorrowBook1(this->name);
	}
	else
		cout << "结果：目前图书馆没有书，借书失败" << endl;
}

void Simple::ReturnBook()
{
	Book temp;
	temp.ReturnBook1();
}

// 管理员
void Admin::AdminRegister()
{
	while (1)
	{
		cout << "请输入你要注册的用户名:> ";
		cin >> name;

		if (FindName(name, A, adminnum) < adminnum)
		{
			cout << "用户名已存在" << endl;
			continue;
		}

		string password1;
		cout << "请输入你要设置的密码: > ";
		cin >> password1;
		cout << "重复你设置的密码:> ";
		cin >> password;
		if (password == password1)
		{
			A[adminnum].name = name;
			A[adminnum].password = password;
			adminnum++;
			cout << "管理员注册成功" << endl;
			break;
		}

		// 到这里两个密码肯定不一样
		cout << "两次密码不一致，请重新输入" << endl;
	}
}

void Admin::AdminLogin()
{
	int flag = 0;
	while (1)
	{
		cout << "请输入你要登录的管理员用户名:>";
		cin >> name;
		int position = FindName(name, A, adminnum);
		if (position >= adminnum)
		{
			cout << "用户不存在" << endl;
			flag = 1;
			break;
		}

		cout << "请输入你的密码: > ";
		cin >> password;
		if (password == A[position].password)
		{
			cout << "登录成功" << endl;
			break;
		}

		// 到这里密码肯定不对
		cout << "密码错误，请重新输入" << endl;
	}

	if (flag)
		return;

	int option = 1;
	while (option)
	{
		cout << "---------------------------------------------------------------" << endl;
		cout << "|          请输入你需要的功能                                  |" << endl;
		cout << "|          1. 增添书               2. 移除书                   |" << endl;
		cout << "|          3. 查询书               4. 查询用户                 |" << endl;
		cout << "|          5. 删除用户             0. 退出                     |" << endl;
		cout << "---------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			AddBook();
		}
		else if (option == 2)
		{
			DelteBook();
		}
		else if (option == 3)
		{
			CheckBook();
		}
		else if (option == 4)
		{
			CheckClient();
		}
		else if (option == 5)
		{
			DeleteClient();
		}
		else if (option != 0)
		{
			cout << "选择错误，请重新输入" << endl;
		}
	}
}

void Admin::CheckBook()
{
	if (booknum == 0)
	{
		cout << "目前图书馆内书的数目：0" << endl;
		return;
	}

	cout << "目前图书馆内书的数目：" << booknum << endl;
	for (int i = 0; i < booknum; i++)
	{
		cout << "****************************************************************************" << endl;
		cout << "书名: " << B[i].GetTitle() << endl;
		cout << "作者: " << B[i].GetAuthor() << endl;
		cout << "出版社: " << B[i].GetPublisher() << endl;
		cout << "单价: " << B[i].GetPrice() << endl;
		cout << "所在位置: " << B[i].GetLocation() << endl;
		cout << "编号: " << B[i].GetCode() << endl;

		if (B[i].IsBorrowed())
		{
			cout << "借阅者: " << B[i].GetBorrower() << endl;
			cout << "应归还日期: " << B[i].GetReturnDate() << endl;
			cout << "状态：已被借出" << endl;
		}
		else
		{
			cout << "状态：未被借出" << endl;
		}
		cout << "****************************************************************************" << endl;
		cout << endl;
	}
}

void Admin::AddBook()
{
	Book book;
	cout << "请输入你要增加的书的标题:> ";
	cin >> book.title;

	cout << "请输入你要增加的书的作者:> ";
	cin >> book.author;

	cout << "请输入你要增加的书的出版社:> ";
	cin >> book.publisher;

	cout << "请输入你要增加的书的价格:> ";
	cin >> book.price;

	cout << "请输入你要增加的书的位置:> ";
	cin >> book.location;
	// 有空格时会出错

	cout << "请输入你要增加的书的编码:> ";
	cin >> book.code;

	book.isborrowed = false;
	book.borrower = "";
	book.returndate = "";
	B[booknum++] = book;
	
	cout << "增添成功" << endl;
}

void Admin::DelteBook()
{
	if (booknum == 0)
	{
		cout << "当前图书馆没有书，删除失败" << endl;
		return;
	}

	cout << "请输入你要删除的书的编码:> ";
	int code;
	cin >> code;

	for (int i = 0; i < booknum; i++)
	{
		if (B[i].code == code)
		{
			for (int j = i + 1; j < booknum; j++)
			{
				B[j] = B[i];
			}
			booknum--;
			cout << "删除成功" << endl;
			return;
		}
	}
	cout << "未查询到此书，删除失败" << endl;
}

void Admin::CheckClient()
{
	cout << "功能：查询用户" << endl;
	
	cout << "****************************普通用户*****************************" << endl;
	if (simplenum != 0)
	{
		for (int i = 0; i < simplenum; i++)
		{
			cout << endl;
			cout << "用户名：" << S[i].name << endl;
			cout << "用户密码：" << S[i].password << endl;
			cout << endl;
		}
	}
	else
		cout << "普通用户数目为0" << endl;
	cout << endl;


	cout << "#############################管理员###############################" << endl;
	for (int i = 0; i < adminnum; i++)
	{
		cout << endl;
		cout << "管理员名：" << A[i].name << endl;
		cout << "管理员密码：" << A[i].password << endl;
		cout << endl;
	}
	cout << endl;
	cout << "查询完毕" << endl;

}

void Admin::DeleteClient()
{
	CheckClient();
	int option = 1;
	while (option)
	{
		cout << "---------------------------------------------------------------" << endl;
		cout << "|          请输入你删除的用户身份                              |" << endl;
		cout << "|          1. 管理员               2. 普通用户                 |" << endl;
		cout << "|          0. 退出                                             |" << endl;
		cout << "---------------------------------------------------------------" << endl;
		cout << "请输入你的选项:> ";
		cin >> option;

		if (option == 1)
		{
			cout << "请输入你要删除的管理员的名字:> ";
			string name;
			cin >> name;
			int position = FindName(name, A, adminnum);
			if (position >= adminnum)
				cout << "该管理员不存在，删除失败" << endl;
			else
			{
				for (int i = position; i < adminnum - 1; i++)
				{
					A[i] = A[i + 1];
				}
				adminnum--;
				cout << "删除成功" << endl;
			}
			break;
		}
		else if (option == 2)
		{
			cout << "请输入你要删除的普通用户的名字:> ";
			string name;
			cin >> name;
			int position = FindName(name, S, simplenum);
			if (position >= simplenum)
				cout << "该用户不存在，删除失败" << endl;
			else
			{
				for (int i = position; i < simplenum - 1; i++)
				{
					S[i] = S[i + 1];
				}
				simplenum--;
				cout << "删除成功" << endl;
			}

			break;
		}
		else if (option != 0)
		{
			cout << "选择错误，请重新输入" << endl;
		}
	}
}

//Book类
string Book::GetTitle()
{ 
	return title;
}

string& Book::GetAuthor()
{
	return author;
}

string Book::GetPublisher()
{
	return publisher;
}

double Book::GetPrice()
{
	return price;
}

bool Book::IsBorrowed()
{ 
	return isborrowed;
}

string Book::GetBorrower()
{ 
	return borrower;
}

string Book::GetReturnDate()
{
	return returndate;
}

string Book::GetLocation()
{
	return location; 
}

int Book::GetCode()
{
	return code;
}

bool Book::BorrowBook1(string name)
{
	int code;
	cout << "请输入你要借的书的编号:> ";
	cin >> code;
	for (int i = 0; i < booknum; i++)
	{
		if (code == B[i].code)
		{
			if (B[i].isborrowed)
			{
				cout << "该书已被借出，无法借阅" << endl;
				return false;
			}
			else
			{
				cout << "借阅成功" << endl;
				B[i].isborrowed = true;
				B[i].borrower = name;

				cout << "请以2024-06-19的格式输入归还日期：> ";
				cin >> B[i].returndate;
				cout << "借阅成功" << endl;
				return true;
			}
		}
	}

	cout << "未找到你需要借的书,借阅失败" << endl;
	return false;
}

void Book::ReturnBook1() 
{
	cout << "请输入你要还的书的编号:>";
	int code;
	cin >> code;
	for (int i = 0; i < booknum; i++)
	{
		if (B[i].code == code)
		{
			B[i].isborrowed = false;
			B[i].borrower = "";
			B[i].returndate = "";
			cout << "归还成功" << endl;
			return;
		}
	}
}

void Book::operator=(const Book& source)
{
	this->title = source.title;
	this->publisher = source.publisher;
	this->author = source.author;
	this->price = source.price;
	this->isborrowed = source.isborrowed;
	this->borrower = source.borrower;
	this->returndate = source.returndate;
	this->location = source.location;
	this->code = source.code;
}

// 文件流
// fstream:读写文件流
// ifstream：读文件流
// ofstream：写文件流

// ifstram.open("你要打开的文件", 打开的方式);
// 打开的方式：以写的方式：ios::in
// 打开的方式：以读的方式 ios::out
// 打开的方式：以二进制的方式 :   ios::binary

void Load()
{
	ifstream ifs;// 读文件
	ifs.open("message.txt", ios::in);

	if (!ifs.is_open())
	{
		// 没有该文件

		// 创建文件
		ofstream ofs;
		ofs.open("message.txt", ios::out);
		ofs.close();
		return;
	}

	// 获取文件大小
	ifs.seekg(0, ios::end);   // 移动文件指针到文件末尾
	streampos fileSize = ifs.tellg(); // 获取文件指针位置，即文件大小
	ifs.seekg(0, std::ios::beg);   // 将文件指针移动回文件开头

	// 判断文件是否有数据
	if (fileSize == 0) 
	{
		return;
	}

	// 读取数据
	string line;
	getline(ifs, line);
	// getline("文件流", 读入的信息存放的字符串);

	// simplenum:普通用户的数目
	// stoi:将字符串转化为整数int
	simplenum = stoi(line);	
	getline(ifs, line);

	// adminnum:管理员的数目
	adminnum = stoi(line);
	getline(ifs, line);

	// booknum:书的数目
	booknum = stoi(line);

	// simple:S数组
	// admin:A数组
	// book:B数组
	for (int i = 0; i < simplenum; i++)
	{
		getline(ifs, line);
		S[i].name = line;

		getline(ifs, line);
		S[i].password = line;
	}
	for (int i = 0; i < adminnum; i++)
	{
		getline(ifs, line);
		A[i].name = line;

		getline(ifs, line);
		A[i].password = line;
	}

	for (int i = 0; i < booknum; i++)
	{
		getline(ifs, line);
		B[i].title = line;

		getline(ifs, line);
		B[i].author = line;

		getline(ifs, line);
		B[i].publisher = line;

		getline(ifs, line);

		// stod:把字符串转化为double
		B[i].price = stod(line);// S

		getline(ifs, line);
		B[i].isborrowed = stoi(line);

		getline(ifs, line);
		B[i].borrower = line;

		getline(ifs, line);
		B[i].returndate = line;

		getline(ifs, line);
		B[i].location = line;

		getline(ifs, line);
		B[i].code = stoi(line);
	}

	ifs.close();
}

void Down()
{
	ofstream ofs;// 写文件
	ofs.open("message.txt", ios::out);

	ofs << simplenum << endl;// simplenum
	ofs << adminnum << endl;// adminnum
	ofs << booknum << endl;// booknum

	for (int i = 0; i < simplenum; i++)
	{
		ofs << S[i].name << endl;// S
		ofs << S[i].password<< endl;// S
	}

	for (int i = 0; i < adminnum; i++)
	{
		ofs << A[i].name << endl;// S
		ofs << A[i].password << endl;// S
	}

	for (int i = 0; i < booknum; i++)
	{
		ofs << B[i].title << endl;
		ofs << B[i].author << endl;
		ofs << B[i].publisher << endl;
		ofs << B[i].price << endl;// S
		ofs << B[i].isborrowed << endl;// S
		ofs << B[i].borrower << endl;// S
		ofs << B[i].returndate << endl;// S
		ofs << B[i].location << endl;// S
		ofs << B[i].code << endl;
	}
	ofs.close();
}

int main()
{
	Load();
	cout << "数据加载成功" << endl;

	Client client;
	Log log;

	Down();
	cout << "数据保存成功" << endl;

	return 0;
}
